package com.y5neko.RadiantKnightExploit;

import com.gn.lab.GNButton;
import com.y5neko.RadiantKnightExploit.UI.AboutStage;
import com.y5neko.RadiantKnightExploit.UI.CheckUpdateStage;
import com.y5neko.RadiantKnightExploit.UI.ProxyStage;
import com.y5neko.RadiantKnightExploit.exp.AssetTypes;
import com.y5neko.RadiantKnightExploit.exp.Shiro.Shiro550;
import com.y5neko.RadiantKnightExploit.exp.VulTypes;
import com.y5neko.RadiantKnightExploit.misc.Tools;
import com.y5neko.RadiantKnightExploit.util.FirstInit;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.*;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import org.jetbrains.annotations.NotNull;
import org.scenicview.ScenicView;

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.image.BufferedImage;
import java.lang.reflect.Method;

public class Main extends Application {
    private MenuBar menuBar;

    public static Image icon = new Image("img/icon.png");   // Image对象是通过底层的构造方法获取文件内容，所以可以直接指定基于resource目录的绝对路径

    private double xOffset = 0;
    private double yOffset = 0;

    public static void main(String[] args) {
        FirstInit.firstInit();
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        /*
          设置一个网格视图
         */
        // 创建一个GridPane并设置其列宽为百分比，以便它们平均分布
        GridPane gridPaneToolBar = new GridPane();gridPaneToolBar.setPadding(new Insets(0, 0, 0, 0));gridPaneToolBar.setHgap(10);gridPaneToolBar.setVgap(10); // 行之间的垂直间距
        // 为GridPane添加三列，并设置它们的百分比宽度
        ColumnConstraints columnToolBar1 = new ColumnConstraints(Region.USE_COMPUTED_SIZE, 33.3, Double.MAX_VALUE);columnToolBar1.setHgrow(Priority.ALWAYS);columnToolBar1.setPercentWidth(33.3);
        ColumnConstraints columnToolBar2 = new ColumnConstraints(Region.USE_COMPUTED_SIZE, 33.4, Double.MAX_VALUE);columnToolBar2.setHgrow(Priority.ALWAYS);columnToolBar2.setPercentWidth(33.4);
        ColumnConstraints columnToolBar3 = new ColumnConstraints(Region.USE_COMPUTED_SIZE, 33.3, Double.MAX_VALUE);columnToolBar3.setHgrow(Priority.ALWAYS);columnToolBar3.setPercentWidth(33.3);
        gridPaneToolBar.getColumnConstraints().addAll(columnToolBar1, columnToolBar2, columnToolBar3);
        HBox.setHgrow(gridPaneToolBar, Priority.ALWAYS);
        // 设置第一个网格为标题栏
        HBox toolBox = new HBox();
        toolBox.setSpacing(2);
        toolBox.setPadding(new Insets(3, 0, 2, 5));
        Image imageIcon = icon;
        ImageView imageViewIcon = new ImageView(imageIcon);
        imageViewIcon.setFitHeight(23);
        imageViewIcon.setPreserveRatio(true);
        buildMenu();
        toolBox.getChildren().add(imageViewIcon);
        toolBox.getChildren().add(menuBar);
        gridPaneToolBar.add(toolBox, 0, 0, 1, 1);
        GridPane.setHalignment(toolBox, HPos.LEFT);
        // 设置第二个网格为标题
        Label titleLabel = new Label("RadiantKnightExploit");
        titleLabel.setFont(new Font("Consolas Bold", 20));

        gridPaneToolBar.add(titleLabel, 1, 0, 1, 1);
        GridPane.setHalignment(titleLabel, HPos.CENTER);
        GridPane.setValignment(titleLabel, VPos.CENTER);
        // 设置第三个网格为窗口操作按钮
        HBox buttonBox = new HBox();
        // 关闭按钮
        Button buttonClose = Tools.getImgButton("img/CloseButton.png");
        buttonClose.setOnAction(e -> {
            primaryStage.close();
            System.exit(0);
        });
        Button buttonMin = Tools.getImgButton("img/MinButton.png");
        buttonMin.setOnAction(e -> primaryStage.setIconified(true));
        Button buttonMax = Tools.getImgButton("img/MaxButton.png");
        buttonMax.setOnAction(e -> {
            e.consume();
            minimizeToTray(primaryStage);
        });
//        buttonMax.setOnAction(e -> {
//            e.consume();
//            if (!primaryStage.isMaximized()) {
//                primaryStage.setMaximized(true);
//            } else {
//                primaryStage.setMaximized(false);
//            }
//        });
        buttonBox.setAlignment(Pos.CENTER_RIGHT);
        buttonBox.getChildren().addAll(buttonClose, buttonMax, buttonMin);
        gridPaneToolBar.add(buttonBox, 2, 0, 1, 1);GridPane.setHalignment(buttonBox, HPos.RIGHT);GridPane.setValignment(buttonBox, VPos.CENTER);

        /*
          创建一个顶部模拟状态栏
         */
        HBox titleBar = new HBox();
        // 绑定拖拽事件
        titleBar.setOnMousePressed(this::handleMousePressed);
        titleBar.setOnMouseDragged(this::handleMouseDragged);
        menuBar.setOnMousePressed(this::handleMousePressed);
        menuBar.setOnMouseDragged(this::handleMouseDragged);

        // 添加一个网格视图
        titleBar.getChildren().add(gridPaneToolBar);
        titleBar.setAlignment(Pos.CENTER); // 居中布局
        titleBar.setPadding(new Insets(0, 0, 0, 0));
        titleBar.setSpacing(0);   // 设置标题栏内间距
        titleBar.setBackground(new Background(new BackgroundFill(Color.WHITE, null, null)));
        // 设置一个BorderPane作为根视图
        BorderPane root = new BorderPane();
        root.setTop(titleBar);







        // 设置一个HBox作为中间内容
        HBox centerBox = new HBox();

        // 设置一个GridPane用于布局中间内容HBox
        GridPane gridPaneCenter = new GridPane(); gridPaneCenter.setPadding(new Insets(0, 0, 0, 0)); gridPaneCenter.setHgap(0); gridPaneCenter.setVgap(0); // 行之间的垂直间距
        ColumnConstraints column1 = new ColumnConstraints(Region.USE_COMPUTED_SIZE, 10, Double.MAX_VALUE); column1.setHgrow(Priority.ALWAYS); column1.setPercentWidth(10);
        ColumnConstraints column2 = new ColumnConstraints(Region.USE_COMPUTED_SIZE, 10, Double.MAX_VALUE); column2.setHgrow(Priority.ALWAYS); column2.setPercentWidth(90);
        gridPaneCenter.getColumnConstraints().addAll(column1, column2);

        // 将GridPane放入HBox，调整HBox样式和布局为自适应
        centerBox.getChildren().add(gridPaneCenter);
        centerBox.setAlignment(Pos.CENTER);
        centerBox.setPadding(new Insets(0, 0, 0, 0));
        centerBox.setBackground(new Background(new BackgroundFill(Color.WHITE, null, null)));
        HBox.setHgrow(gridPaneCenter, Priority.ALWAYS);
        root.setCenter(centerBox);
        HBox bottomBox = new HBox();
        bottomBox.setPadding(new Insets(2, 5, 2, 5));
        bottomBox.setStyle("-fx-background-color: #99ccff;");
        bottomBox.setAlignment(Pos.CENTER_RIGHT);
        Label bottomLabel = new Label("Powered by Y5neKO");
        bottomBox.getChildren().add(bottomLabel);
        root.setBottom(bottomBox);

            /*
              设置第一列为资产类型
             */
            VBox assetTypeBox = new VBox();

            ScrollPane scrollPaneATB = Tools.getScrollPane(assetTypeBox, true);
            centerBox.layoutBoundsProperty().addListener((observable, oldValue, newValue) -> scrollPaneATB.setMinHeight(newValue.getHeight())); // 动态更新高度
            gridPaneCenter.add(scrollPaneATB, 0, 0, 1, 1);

            // 设置第二列为资产漏洞利用详情
            HBox assetVulDetailBox = new HBox();
            // 包含两列，第一列为滚动框，第二列为漏洞利用模块
            GridPane gridPaneAssetVulDetail = new GridPane();gridPaneAssetVulDetail.setPadding(new Insets(0, 0, 0, 0));gridPaneAssetVulDetail.setHgap(0);gridPaneAssetVulDetail.setVgap(0); // 行之间的垂直间距
            ColumnConstraints columnVulTypes = new ColumnConstraints(Region.USE_COMPUTED_SIZE, 10, Double.MAX_VALUE);columnVulTypes.setHgrow(Priority.ALWAYS); //columnVulTypes.setPercentWidth(10);
            ColumnConstraints columnExp = new ColumnConstraints(Region.USE_COMPUTED_SIZE, 10, Double.MAX_VALUE);columnExp.setHgrow(Priority.ALWAYS); columnExp.setPercentWidth(85);
            gridPaneAssetVulDetail.getColumnConstraints().addAll(columnVulTypes, columnExp);


            // 默认获取Shiro的漏洞按钮
            HBox expBox = Shiro550.getHBox();
            // 默认获取Shiro的漏洞按钮
            VBox vulTypeBox = Tools.getVulTypeBox(VulTypes.ShiroVulTypes, gridPaneAssetVulDetail, "Shiro", expBox);

            ScrollPane scrollPaneVTB = Tools.getScrollPane(vulTypeBox, false);     // 获取一个漏洞列表ScrollPane，并放入漏洞列表VBox
            centerBox.layoutBoundsProperty().addListener((observable, oldValue, newValue) -> scrollPaneVTB.setMinHeight(newValue.getHeight())); // 动态更新高度
            gridPaneAssetVulDetail.add(scrollPaneVTB, 0, 0, 1, 1);  // 把漏洞列表ScrollPane放进漏洞详情GridPane的第一个表格里
            gridPaneAssetVulDetail.add(expBox, 1, 0, 1, 1);


        // 放入所有节点
        HBox.setHgrow(gridPaneAssetVulDetail, Priority.ALWAYS);
        assetVulDetailBox.getChildren().add(gridPaneAssetVulDetail);    // 将漏洞详情GridPane放进漏洞详情HBox
        // 设置资产漏洞利用详情的HBox布局
        assetVulDetailBox.setAlignment(Pos.CENTER);
        assetVulDetailBox.setPadding(new Insets(0, 0, 0, 0));
        assetVulDetailBox.setBackground(new Background(new BackgroundFill(Color.WHITE, null, null)));

        // 将漏洞详情HBox放进最外层GridPane
        gridPaneCenter.add(assetVulDetailBox, 1, 0, 1, 1);


        // 向资产滚动框放入按钮并绑定事件
        for (String assetType : AssetTypes.assetTypes) {
            GNButton buttonAsset = Tools.getGNButton(AssetTypes.getAssetTypeString(assetType));
            buttonAsset.setOnMouseClicked(event -> {
                System.out.println(assetType);

                try {
                    Class<?> clazz = Class.forName("com.y5neko.RadiantKnightExploit.exp." + assetType + "." + VulTypes.getVulType(assetType));
                    Method method = clazz.getMethod("getHBox");
                    HBox expBox1 = (HBox) method.invoke(null);      // 反射获取一个指定漏洞利用的VBox

                    VBox vulTypeBox1 = Tools.getVulTypeBox(VulTypes.getVulTypes(assetType), gridPaneAssetVulDetail, assetType, expBox1);    // 获取一个含有指定资产所有漏洞的漏洞列表VBox，并且通过重载方法绑定事件

                    ScrollPane scrollPaneVTB2 = Tools.getScrollPane(vulTypeBox1, false);     // 获取一个漏洞列表ScrollPane，并放入漏洞列表VBox
                    scrollPaneVTB2.setMinHeight(centerBox.getHeight());

                    gridPaneAssetVulDetail.getChildren().clear();
                    System.out.println("清除了滚动条2和内侧HBox");
                    gridPaneAssetVulDetail.add(scrollPaneVTB2, 0, 0, 1, 1);
                    gridPaneAssetVulDetail.add(expBox1, 1,0,1,1);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });
            assetTypeBox.getChildren().add(buttonAsset);
        }






        /*
          圆角设计
         */
        Rectangle clipRectangle = new Rectangle();
        clipRectangle.setArcWidth(20);
        clipRectangle.setArcHeight(20);
        clipRectangle.setWidth(1300);
        clipRectangle.setHeight(800);
        root.setClip(clipRectangle);

        /*
          开始处理Stage和放入Scene
         */
        Scene scene = new Scene(root);
        scene.setFill(Color.TRANSPARENT);   // 圆角|透明
        scene.getStylesheets().add("css/Style.css");
        // 设置stage为无状态栏型
        primaryStage.initStyle(StageStyle.UNDECORATED);
        primaryStage.initStyle(StageStyle.TRANSPARENT); // 圆角|透明
        primaryStage.setScene(scene);
        primaryStage.setTitle("RadiantKnightExploit");
        primaryStage.setHeight(800);
        primaryStage.setWidth(1300);
        primaryStage.getIcons().add(icon);

        primaryStage.show();
        ScenicView.show(scene);
    }

    /**
     * 构建顶部菜单
     */
    private void buildMenu(){
        menuBar = new MenuBar();
        menuBar.setStyle("-fx-background-color: transparent;");
        menuBar.setPadding(new Insets(0));
        Menu settingMenu = new Menu("设置");
        Menu helpMenu = new Menu("帮助");
        menuBar.getMenus().addAll(settingMenu, helpMenu);

        MenuItem settingProxy = new MenuItem("代理设置");
        settingMenu.getItems().addAll(settingProxy);
        settingProxy.setOnAction(event -> new ProxyStage());

        MenuItem about = new MenuItem("关于");
        helpMenu.getItems().addAll(about);
        about.setOnAction(event -> new AboutStage());

        MenuItem checkUpdate = new MenuItem("检查更新");
        helpMenu.getItems().add(checkUpdate);
        checkUpdate.setOnAction(event -> new CheckUpdateStage());
    }

    /**
     * 处理鼠标按下事件
      */
    private void handleMousePressed(MouseEvent event) {
        // 获取鼠标相对于窗口的坐标
        xOffset = event.getSceneX();
        yOffset = event.getSceneY();
    }

    /**
     * 处理鼠标拖动事件
     * @param event 鼠标事件
     */
    private void handleMouseDragged(MouseEvent event) {
        // 计算窗口的新位置（基于鼠标移动的距离）
        double newX = event.getScreenX() - xOffset;
        double newY = event.getScreenY() - yOffset;

        // 移动窗口到新位置
        Stage stage = (Stage) ((event.getSource() instanceof Node) ? ((Node) event.getSource()).getScene().getWindow() : null);
        if (stage != null) {
            stage.setX(newX);
            stage.setY(newY);
        }
    }

    private void minimizeToTray(Stage primaryStage) {
        Platform.setImplicitExit(false);
        // 隐藏JavaFX Stage
        primaryStage.hide();

        BufferedImage bufferedImage = SwingFXUtils.fromFXImage(icon, null);

        TrayIcon trayIcon = getTrayIcon(primaryStage, bufferedImage);
        trayIcon.setImageAutoSize(true);

        // 检查系统托盘是否可用并添加图标
        if (SystemTray.isSupported()) {
            SystemTray tray = SystemTray.getSystemTray();
            try {
                tray.add(trayIcon);
            } catch (AWTException e) {
                System.err.println(e.getMessage());
            }
        }
    }

    private static @NotNull TrayIcon getTrayIcon(Stage primaryStage, BufferedImage bufferedImage) {
        PopupMenu popup = new PopupMenu();
        java.awt.MenuItem exitItem = new java.awt.MenuItem("Exit");
        exitItem.addActionListener(e -> System.exit(0));
        popup.add(exitItem);

        // 创建TrayIcon并添加事件监听器
        TrayIcon trayIcon = new TrayIcon(bufferedImage, "RadiantKnightExploit", popup);
        trayIcon.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(java.awt.event.MouseEvent e) {
                if (e.getClickCount() == 2) {
                    // 双击托盘图标时恢复窗口
                    Platform.runLater(primaryStage::show);
                    SystemTray.getSystemTray().remove(trayIcon);
                }
            }
        });
        return trayIcon;
    }
}